package com.ohuang.test_compose.composeView

import android.util.Log
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.gestures.animateScrollBy
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInParent
import kotlinx.coroutines.launch
import java.util.LinkedList
import java.util.TreeMap

/**
 *
 * 可滚动 ScrollableColumn
 * ScrollableColumn(){
 * Item{  //需要item才能滚动到固定位置
 *
 *
 * }
 * }
 *
 */

@Composable
inline fun ScrollableColumn(
    modifier: Modifier = Modifier,
    scrollableState: ScrollableState = rememberScrollableState(),
    content: ScrollableScope.() -> Unit
) {

    val scrollableScopeImpl = ScrollableScopeColumnImpl()
    val rememberCoroutineScope = rememberCoroutineScope()

    Column(
        modifier = Modifier
            .then(modifier)
            .verticalScroll(scrollableState.scrollState)
            .onGloballyPositioned {
                rememberCoroutineScope.launch {
                    scrollableState.dispatchLazyScroll()
                }
            }
    ) {
        content(scrollableScopeImpl)
        scrollableScopeImpl.composeList.forEachIndexed { index, function ->
            Box(modifier = Modifier.onGloballyPositioned { layoutCoordinates ->
                scrollableState.positionMap[index] = layoutCoordinates.positionInParent().y
            }) {
                function()
            }
        }
    }

}

@Composable
inline fun ScrollableRow(
    modifier: Modifier = Modifier,
    scrollableState: ScrollableState = rememberScrollableState(),
    content: ScrollableScope.() -> Unit
) {

    val scrollableScopeImpl = ScrollableScopeColumnImpl()
    val rememberCoroutineScope = rememberCoroutineScope()

    Row(
        modifier = Modifier
            .then(modifier)
            .horizontalScroll(scrollableState.scrollState)
            .onGloballyPositioned {
                rememberCoroutineScope.launch {
                    scrollableState.dispatchLazyScroll()
                }
            }
    ) {
        content(scrollableScopeImpl)
        scrollableScopeImpl.composeList.forEachIndexed { index, function ->
            Box(modifier = Modifier.onGloballyPositioned { layoutCoordinates ->
                scrollableState.positionMap[index] = layoutCoordinates.positionInParent().x
            }) {
                function()
            }
        }
    }

}

@Composable
fun rememberScrollableState(): ScrollableState {
    val rememberScrollState = rememberScrollState()
    val positionMap = remember {
        TreeMap<Any, Float>()
    }
    val position = remember {
        Position(-1)
    }
    return ScrollableState(rememberScrollState, positionMap, position)
}

class Position(var value: Int)

@Stable
class ScrollableState(
    val scrollState: ScrollState,
    val positionMap: TreeMap<Any, Float>,
    val p: Position = Position(-1)
) {

    /**
     * 需要重组后滚动到相应位置,调用此方法。
     */
    suspend fun lazyAnimateScrollToItem(position: Int) {
        val fl = positionMap[position]
        if (position >= 0) {
            p.value = position
        }
        fl?.let {
            scrollState.animateScrollTo(fl.toInt())
        }
    }

    @PublishedApi
    internal suspend fun dispatchLazyScroll() {
        val lazyPosition1 = p.value
        p.value = -1
        if (lazyPosition1 >= 0) {
            animateScrollToItem(lazyPosition1)
        }
    }

    /**
     * 滚动到当前重组位置。如果需要等待重组后,再滚动请使用lazyAnimateScrollToItem。
     */
    suspend fun animateScrollToItem(position: Int) {
        val fl = positionMap[position]
        fl?.let {
            scrollState.animateScrollTo(fl.toInt())
        }
        if (fl == null) {
            if (position < 0) {
                scrollState.animateScrollTo(0)
            }
            if (position > positionMap.size) {
                var maxValue = 0F
                positionMap.iterator().forEach { data ->
                    val value = data.value
                    maxValue = Math.max(value, maxValue)
                }
                scrollState.animateScrollTo(maxValue.toInt())
            }
        }
    }

    suspend fun animateScrollTo(p: Int) {
        scrollState.animateScrollTo(p)
    }

    suspend fun animateScrollBy(value: Float) {
        scrollState.animateScrollBy(value)
    }

}

@PublishedApi
internal class ScrollableScopeColumnImpl() : ScrollableScope {


    val composeList = LinkedList<@Composable () -> Unit>()

    override fun item(content: @Composable () -> Unit) {
        composeList.add(content)
    }
}


interface ScrollableScope {

    fun item(content: @Composable () -> Unit)
}